using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Security.Permissions;
using MEA.AE_Data;
using MEA.AE_Data.Config;

namespace MEA.Chart
{
	public class Function
	{
		public enum EGraphicFunctSelect
		{
			eNotSelected,
			eSelected,
			eWasSelected
		}

		private struct SLuftDruck
		{
			public int hohe;

			public int druck;

			public SLuftDruck(int h, int d)
			{
				hohe = h;
				druck = d;
			}
		}

		public List<PointF> points;

		public ArrayList timestamps;

		public PointF[] points_bild;

		public PointF[] points_wert;

		public Hashtable sessionMarkers;

		public Hashtable SessionMarkerComment;

		public PointF selected_point;

		private DateTime ptTimestamp;

		private EGraphicFunctSelect isselected;

		public Koordsyst koordsyst;

		private Pen pen;

		public PointF lastaddedpoint;

		public bool isconstant;

		public string name;

		private string unit;

		private string selPtTimestampFormat_s;

		private int maxpoints;

		private bool visible;

		private bool update;

		public string Ecu_message;

		public ConfigLiveView.ESignals Ecu_Emessage;

		public ConfigData.e_ECUS AB = ConfigData.e_ECUS.ECU_A;

		private static bool sessionMarkerWritte;

		public int fncStartPos;

		private SLuftDruck[] sLuftDruck = new SLuftDruck[26]
		{
			new SLuftDruck(-200, 1040),
			new SLuftDruck(-100, 1026),
			new SLuftDruck(0, 1013),
			new SLuftDruck(100, 1000),
			new SLuftDruck(200, 988),
			new SLuftDruck(300, 975),
			new SLuftDruck(400, 962),
			new SLuftDruck(500, 950),
			new SLuftDruck(600, 938),
			new SLuftDruck(700, 926),
			new SLuftDruck(800, 914),
			new SLuftDruck(900, 903),
			new SLuftDruck(1000, 891),
			new SLuftDruck(1500, 836),
			new SLuftDruck(2000, 784),
			new SLuftDruck(2500, 735),
			new SLuftDruck(3000, 689),
			new SLuftDruck(3500, 646),
			new SLuftDruck(4000, 606),
			new SLuftDruck(5000, 533),
			new SLuftDruck(5400, 507),
			new SLuftDruck(6000, 469),
			new SLuftDruck(7000, 412),
			new SLuftDruck(8000, 363),
			new SLuftDruck(10000, 281),
			new SLuftDruck(13000, 191)
		};

		[Category("Style")]
		[Description("Color of the function")]
		public Color PenColor
		{
			get
			{
				return pen.Color;
			}
			set
			{
				pen.Color = value;
				update = true;
			}
		}

		[Description("Visibility of the function")]
		[Category("Style")]
		public bool Visible
		{
			get
			{
				return visible;
			}
			set
			{
				visible = value;
				update = true;
			}
		}

		[Description("Name")]
		public string Name
		{
			get
			{
				return name;
			}
		}

		[Description("Unit")]
		public string UNIT
		{
			get
			{
				return unit;
			}
		}

		[Description("Line-width of the function")]
		[Category("Style")]
		public float PenWidth
		{
			get
			{
				return pen.Width;
			}
			set
			{
				pen.Width = value;
				if (pen.Width <= 0f)
				{
					pen.Width = 1f;
				}
				update = true;
			}
		}

		[Category("Data")]
		[Description("Maximum of Points that are stored")]
		[Browsable(false)]
		public int MaxPoints
		{
			get
			{
				return maxpoints;
			}
			set
			{
				maxpoints = value;
			}
		}

		public bool SessionMarkerWritten
		{
			get
			{
				return sessionMarkerWritte;
			}
			set
			{
				sessionMarkerWritte = value;
			}
		}

		public DateTime PtTimestamp
		{
			get
			{
				return ptTimestamp;
			}
			set
			{
				ptTimestamp = value;
			}
		}

		public EGraphicFunctSelect IsSelected
		{
			get
			{
				return isselected;
			}
			set
			{
				isselected = value;
			}
		}

		public Function(Koordsyst c, Color color, string name, int maxpoints, string unit, string timestampFormat)
		{
			koordsyst = c;
			timestamps = new ArrayList();
			points = new List<PointF>();
			sessionMarkers = new Hashtable();
			SessionMarkerComment = new Hashtable();
			pen = new Pen(color, 1f);
			isselected = EGraphicFunctSelect.eNotSelected;
			this.name = name;
			visible = false;
			this.unit = unit;
			if (name[0] == 'A')
			{
				AB = ConfigData.e_ECUS.ECU_A;
			}
			else if (name[0] == 'B')
			{
				AB = ConfigData.e_ECUS.ECU_B;
			}
			if (timestampFormat != null)
			{
				selPtTimestampFormat_s = timestampFormat;
			}
			else
			{
				selPtTimestampFormat_s = "dd.MM.yy HH:mm:ss";
			}
			if (maxpoints == -1)
			{
				this.maxpoints = int.MaxValue;
			}
			else
			{
				this.maxpoints = maxpoints;
			}
			points_bild = new PointF[1024];
			points_wert = new PointF[1024];
		}

		public Function(Koordsyst c, ref Var varx, string timestampFormat, int maxpoints)
		{
			koordsyst = c;
			timestamps = new ArrayList();
			points = new List<PointF>();
			sessionMarkers = new Hashtable();
			SessionMarkerComment = new Hashtable();
			pen = new Pen(varx.LineColor, 1f);
			isselected = EGraphicFunctSelect.eNotSelected;
			name = varx.Name;
			visible = false;
			unit = ConfigLiveView.SigClass[(int)varx.SigClass].Unit;
			Ecu_message = varx.Ecu_message;
			Ecu_Emessage = varx.Ecu_Emessage;
			if (name[0] == 'A')
			{
				AB = ConfigData.e_ECUS.ECU_A;
			}
			else if (name[0] == 'B')
			{
				AB = ConfigData.e_ECUS.ECU_B;
			}
			if (timestampFormat != null)
			{
				selPtTimestampFormat_s = timestampFormat;
			}
			else
			{
				selPtTimestampFormat_s = "dd.MM.yy HH:mm:ss";
			}
			if (maxpoints == -1)
			{
				this.maxpoints = int.MaxValue;
			}
			else
			{
				this.maxpoints = maxpoints;
			}
			points_bild = new PointF[1024];
			points_wert = new PointF[1024];
		}

		public void AddPoint(ref PointF p)
		{
			points.Add(p);
			lastaddedpoint = p;
		}

		public void AddPoints(ref List<PointF> ps)
		{
			points.AddRange(ps);
			lastaddedpoint = points[ps.Count - 1];
		}

		public void Move(float x)
		{
			Hashtable hashtable = new Hashtable();
			Hashtable hashtable2 = new Hashtable();
			int index = points.IndexOf(selected_point);
			for (int i = 0; i < points.Count; i++)
			{
				PointF pointF = points[i];
				PointF value = points[i];
				value.X += x;
				points[i] = value;
				if (sessionMarkers.ContainsKey(pointF))
				{
					DateTime dateTime = (DateTime)sessionMarkers[pointF];
					try
					{
						hashtable.Add(points[i], dateTime);
					}
					catch
					{
					}
				}
				if (SessionMarkerComment.ContainsKey(pointF))
				{
					string value2 = (string)SessionMarkerComment[pointF];
					try
					{
						hashtable2.Add(points[i], value2);
					}
					catch
					{
					}
				}
			}
			if (isselected != EGraphicFunctSelect.eNotSelected)
			{
				try
				{
					selected_point = points[index];
				}
				catch
				{
				}
			}
			sessionMarkers = hashtable;
			SessionMarkerComment = hashtable2;
		}

		[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
		public void Draw(ref Graphics g, bool all)
		{
			if (!visible || points.Count <= 2)
			{
				return;
			}
			int i = 0;
			if (all || update)
			{
				for (update = false; points[i].X < koordsyst.XMin && i < points.Count - 1; i++)
				{
				}
				i--;
			}
			else
			{
				i = points.Count - 3;
			}
			if (i < 0)
			{
				i = 0;
			}
			fncStartPos = i;
			StringFormat format = new StringFormat(StringFormatFlags.DirectionVertical);
			string empty = string.Empty;
			lock (g)
			{
				for (; i < points.Count - 1; i++)
				{
					if (!(points[i].X <= koordsyst.XMax) || !(points[i].X >= koordsyst.XMin))
					{
						continue;
					}
					PointF pt = koordsyst.transformToBild(new PointF[1] { points[i] });
					object obj = sessionMarkers[points[i]];
					if (obj == null)
					{
						PointF pt2 = koordsyst.transformToBild(new PointF[1] { points[i + 1] });
						g.DrawLine(pen, pt, pt2);
						continue;
					}
					if (sessionMarkers[points[i + 1]] == null)
					{
						PointF pt2 = koordsyst.transformToBild(new PointF[1] { points[i + 1] });
						g.DrawLine(pen, pt, pt2);
					}
					object obj2 = SessionMarkerComment[points[i]];
					empty = ((obj2 == null) ? string.Empty : ((string)obj2));
					g.DrawRectangle(pen, pt.X - 3f, pt.Y - 3f, 6f, 6f);
					if (sessionMarkerWritte)
					{
						g.DrawString(string.Format("{0} {1}", obj, empty), new Font(FontFamily.GenericSansSerif, 8f, FontStyle.Bold), new SolidBrush(Color.FromArgb(208, PenColor)), pt.X - 20f, pt.Y - 100f, format);
					}
				}
				sessionMarkerWritte = false;
				if (isselected != EGraphicFunctSelect.eNotSelected)
				{
					PointF point = koordsyst.transformToBild(selected_point.X, selected_point.Y);
					bool flag = false;
					if (point.X > koordsyst.Offset.X && point.X < (float)koordsyst.BILD_WIDTH)
					{
						g.DrawRectangle(pen, point.X - 3f, point.Y - 3f, 6f, 6f);
						flag = true;
					}
					string yAxeText = koordsyst.YAxeText;
					string text;
					switch (koordsyst.Format)
					{
					case ConfigBase.EStringFormat.e_Bin:
					{
						int input = Convert.ToInt32(selected_point.Y);
						text = ConvertToBinaryString(input);
						break;
					}
					case ConfigBase.EStringFormat.e_F0:
						text = string.Format(ConfigBase.StrStringFormat[5], (int)selected_point.Y);
						break;
					case ConfigBase.EStringFormat.e_X1:
					case ConfigBase.EStringFormat.e_X2:
					case ConfigBase.EStringFormat.e_X4:
					case ConfigBase.EStringFormat.e_X8:
						text = string.Format(ConfigBase.StrStringFormat[(uint)koordsyst.Format], (int)selected_point.Y);
						break;
					default:
						text = string.Format(ConfigBase.StrStringFormat[(uint)koordsyst.Format], selected_point.Y);
						break;
					}
					if (point.Y > (float)(koordsyst.BILD_HEIGHT - 50))
					{
						point.Y -= 36f;
					}
					else
					{
						point.Y += 2f;
					}
					if (point.X > (float)(koordsyst.BILD_WIDTH - 100))
					{
						point.X -= 100f;
					}
					else
					{
						point.X += 5f;
					}
					if (flag)
					{
						ConfigLiveView.ESignals ecu_Emessage = Ecu_Emessage;
						empty = ((ecu_Emessage != ConfigLiveView.ESignals.e_APSCD_pVal) ? string.Format("{0}\r\n{1} {2},\r\n{3}", name, text, yAxeText, ptTimestamp.ToString(selPtTimestampFormat_s)) : string.Format("{0}\r\n{1} {2};  Press.Alt.: {4:F1} [ft] \r\n{3}", name, text, yAxeText, ptTimestamp.ToString(selPtTimestampFormat_s), luftDruckF(selected_point.Y)));
						g.DrawString(empty, new Font(FontFamily.GenericSansSerif, 8f, FontStyle.Bold), new SolidBrush(Color.FromArgb(192, PenColor)), point);
					}
				}
			}
		}

		private float luftDruckF(float druck)
		{
			float num = 0f;
			int num2 = 0;
			SLuftDruck sLuftDruck = this.sLuftDruck[num2];
			while (druck <= (float)sLuftDruck.druck)
			{
				sLuftDruck = this.sLuftDruck[++num2];
			}
			SLuftDruck sLuftDruck2 = this.sLuftDruck[num2 - 1];
			num = (float)(sLuftDruck.hohe - sLuftDruck2.hohe) / (float)(sLuftDruck.druck - sLuftDruck2.druck);
			num *= druck - (float)sLuftDruck2.druck;
			num += (float)sLuftDruck2.hohe;
			return num * 3.28f;
		}

		public void DrawLastAddedPoint(Graphics g)
		{
			if (!visible)
			{
				return;
			}
			int count = points.Count;
			if (count <= 1)
			{
				return;
			}
			PointF pointF = points[count - 2];
			PointF pointF2 = lastaddedpoint;
			if (!(pointF.X >= koordsyst.XMin) || !(pointF.X <= koordsyst.XMax) || !(pointF2.X >= koordsyst.XMin) || !(pointF2.X <= koordsyst.XMax))
			{
				return;
			}
			PointF pt = koordsyst.transformToBild(new PointF[1] { pointF });
			PointF pt2 = koordsyst.transformToBild(new PointF[1] { pointF2 });
			try
			{
				lock (g)
				{
					g.DrawLine(pen, pt, pt2);
				}
			}
			catch (Exception ex)
			{
				Console.WriteLine("DrawLastAddedPoint " + ex.ToString());
			}
		}

		private string ConvertToBinaryString(int input)
		{
			string text = null;
			string text2 = null;
			int num = 7;
			if ((double)koordsyst.YMax > Math.Pow(2.0, 16.0))
			{
				num = 31;
			}
			else if ((double)koordsyst.YMax > Math.Pow(2.0, 8.0))
			{
				num = 15;
			}
			while (num >= 0)
			{
				text = ((((input >> num) & 1) != 1) ? "0" : "1");
				text2 += text;
				if (num % 8 == 0)
				{
					text2 += " ";
				}
				num--;
			}
			return text2;
		}

		public void Select()
		{
			if (isselected != EGraphicFunctSelect.eNotSelected)
			{
				PenWidth = 2f;
			}
			koordsyst.YKoordRaster = true;
		}

		public void DeSelect()
		{
			if (isselected != EGraphicFunctSelect.eNotSelected)
			{
				isselected = EGraphicFunctSelect.eWasSelected;
			}
			PenWidth = 1f;
			koordsyst.YKoordRaster = true;
		}

		public bool isPoint(PointF q, ref PointF p1, ref PointF p2, ref int muDataPos)
		{
			float num = 1f;
			muDataPos = -1;
			bool flag = false;
			if (points.Count > 1)
			{
				num = Math.Abs(points[1].X - points[0].X);
				if (num != 1f && num != 0.1f)
				{
					float num2 = Math.Abs(points[2].X - points[1].X);
					if (num != num2)
					{
						num = num2;
					}
				}
				float num3 = koordsyst.XLen / (float)koordsyst.BILD_WIDTH * 20f * num;
				float num4 = koordsyst.YLen / (float)koordsyst.BILD_HEIGHT * 20f;
				if (num3 < Math.Abs(points[0].X - points[1].X))
				{
					num3 = Math.Abs(points[0].X - points[1].X);
				}
				int num5 = Math.Abs((int)(q.X / num));
				num5 = points.Count - 2;
				for (int num6 = num5; num6 >= 0 && !flag; num6--)
				{
					p1 = points[num6];
					p2 = points[num6 + 1];
					if ((int)q.X != (int)p1.X)
					{
						flag = false;
						continue;
					}
					flag = true;
					if (q.Y <= p1.Y - num4 || q.Y > p2.Y + num4)
					{
						if (q.Y <= p2.Y - num4 || q.Y > p1.Y + num4)
						{
							flag = false;
							continue;
						}
						flag = true;
					}
					else
					{
						flag = true;
					}
					if (flag)
					{
						muDataPos = num6;
					}
				}
			}
			return flag;
		}

		public bool SelectNeighborPoint(bool left, ref int pointXPos, ConfigBase.EGraphicAspect aspect)
		{
			bool result = false;
			if (isselected != EGraphicFunctSelect.eNotSelected)
			{
				int count = points.Count;
				if (left)
				{
					if (aspect == ConfigBase.EGraphicAspect.eShowGraphDataLog)
					{
						for (int i = 0; i < points.Count; i++)
						{
							if (points[i].Equals(selected_point))
							{
								if (i < points.Count)
								{
									pointXPos = i + 1;
									selected_point = points[pointXPos];
								}
								result = true;
								break;
							}
						}
					}
					else
					{
						for (int j = 0; j < points.Count; j++)
						{
							if (points[j].Equals(selected_point))
							{
								if (j < points.Count)
								{
									pointXPos = j - 1;
									selected_point = points[pointXPos];
								}
								else
								{
									pointXPos = j;
								}
								result = true;
								break;
							}
						}
					}
				}
				else if (aspect == ConfigBase.EGraphicAspect.eShowGraphDataLog)
				{
					for (int k = 0; k < points.Count; k++)
					{
						if (points[k].Equals(selected_point))
						{
							if (k > 0)
							{
								pointXPos = k - 1;
								selected_point = points[pointXPos];
							}
							else
							{
								pointXPos = k;
							}
							result = true;
							break;
						}
					}
				}
				else
				{
					for (int l = 0; l < points.Count; l++)
					{
						if (points[l].Equals(selected_point))
						{
							if (l < points.Count)
							{
								pointXPos = l + 1;
								selected_point = points[pointXPos];
							}
							else
							{
								pointXPos = l;
							}
							result = true;
							break;
						}
					}
				}
			}
			return result;
		}

		public override string ToString()
		{
			return name;
		}
	}
}
